use std::cell::RefCell;
use std::collections::HashMap;
use std::env::var;
use std::rc::Rc;
use crate::callable::{Clock, LoxCallable, LoxClass, LoxFunction, LoxInstance};
use crate::expr::{Expression, ExprTrait, ExprVisitor, EvaluateResult, Binary, EvaluatedValue, Literal, Unary, Triple, Variable, Assign, Logical, Call, Grouping, Get, Set, This, Super};
use crate::interpreter::ExecErr::Other;
use crate::parser::Parser;
use crate::scanner::{LiteralValue, Scanner, Token, TokenType};
use crate::stmt::{Stmt, StmtBlock, StmtClass, StmtExpr, StmtFunction, StmtIf, StmtPrint, StmtReturn, StmtTrait, StmtVar, StmtVisitor, StmtWhile};


#[derive(Debug)]
pub struct Environment {
    pub values: HashMap<String, EvaluatedValue>,
    pub enclosing: Option<Rc<RefCell<Environment>>>,
}

impl Environment {
    pub fn new() -> Self {
        Self { values: HashMap::new(), enclosing: None}
    }

    pub fn with_enclosing(env: Rc<RefCell<Environment>>) -> Self {
        Self { values: HashMap::new(), enclosing: Some(env)}
    }

    pub fn define(&mut self, name: String, value: EvaluatedValue) {
        self.values.insert(name, value);
    }

    pub fn get(&self, name: &Token) -> Option<EvaluatedValue> {
        match self.values.get(&name.lexeme) {
            Some(v) => Some(v.clone()),
            None => None
        }
    }

    pub fn get_at(&self, name: &str, distance: usize) -> Option<EvaluatedValue> {
        if distance == 0 {
            let ret = match self.values.get(name) {
                Some(v) => Some(v.clone()),
                None => None
            };

            println!("get {} at {}, value = {:?}", name, distance, ret);

            return ret;
        }

        let mut current_env = match self.enclosing {
            None => return None,
            Some(ref env) => env.clone()
        };

        for _ in 0..distance - 1 {
            let mut parent_found = false;

            if current_env.borrow().enclosing.is_some() {
                parent_found = true;
            }

            if parent_found {
                let tmp = current_env.borrow().enclosing.as_ref().unwrap().clone();
                current_env = tmp;
            } else {
                return None;
            }
        }

        let env_ref = current_env.borrow();
        return env_ref.get_at(name, 0)
    }

    pub fn assign(&mut self, name: String, value: EvaluatedValue) -> bool {
        if self.values.contains_key(&name) {
            self.values.insert(name, value);
            true
        } else {
            match self.enclosing {
                None => false,
                Some(ref enclosing) => {
                    enclosing.borrow_mut().assign(name, value)
                }
            }
        }
    }

    pub fn assign_at(&mut self, name: String, value: EvaluatedValue, distance: usize) -> bool {
        if distance == 0 {
            return if self.values.contains_key(&name) {
                self.values.insert(name, value);
                true
            } else {
                false
            }
        }

        let mut current_env = match self.enclosing {
            None => return false,
            Some(ref env) => env.clone()
        };

        for _ in 0..distance - 1 {
            let mut parent_found = false;

            if current_env.borrow().enclosing.is_some() {
                parent_found = true;
            }

            if parent_found {
                let tmp = current_env.borrow().enclosing.as_ref().unwrap().clone();
                current_env = tmp;
            } else {
                return false;
            }
        }

        if current_env.borrow().values.contains_key(&name) {
            current_env.borrow_mut().values.insert(name, value);
            true
        } else {
            false
        }
    }
}

pub struct Interpreter {
    globals: Rc<RefCell<Environment>>,
    env: Rc<RefCell<Environment>>,
    locals: HashMap<Expression, usize>
}


#[derive(Debug)]
pub enum ExecErr {
    Break,
    Continue,
    Return(EvaluatedValue),
    Other(String)
}

pub type ExecResult = Result<EvaluatedValue, ExecErr>;


impl Interpreter {
    pub fn new() -> Self {
        let mut env = Rc::new(RefCell::new(Environment::new()));
        env.borrow_mut().define("clock".to_string(), EvaluatedValue::Call(Rc::new(Clock{})));
        Self { globals: env.clone(), env: env, locals: HashMap::new() }
    }
}

impl ExprVisitor<EvaluateResult> for Interpreter {
    fn visit_binary_expr(&mut self, binary: &Binary) -> EvaluateResult {
        let left_val = self.evaluate(&binary.left)?;
        let right_val = self.evaluate(&binary.right)?;
        let operator = &binary.operator;

        let mut ret = get_invalid_binary_error(&binary.left, operator, &binary.right);

        let expr_tuple = (&left_val, &right_val);
        match operator.t_type {
            TokenType::Plus => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::String(ls)), EvaluatedValue::Literal(LiteralValue::String(rs))) => {
                        ret = Ok(EvaluatedValue::new_string(format!("{}{}", ls, rs)))
                    }
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_number(ln + rn))
                    }
                    (EvaluatedValue::Literal(LiteralValue::String(ln)), EvaluatedValue::Literal(LiteralValue::Number(lr))) => {
                        ret = Ok(EvaluatedValue::new_string(format!("{}{}", ln, *lr)))
                    }
                    _ => {}
                }
            }
            TokenType::Minus => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_number(ln - rn))
                    }
                    _ => {}
                }
            }
            TokenType::Star => {
                match &expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_number(ln * rn))
                    }
                    _ => {}
                }
            }
            TokenType::Slash => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        if *rn == 0.0_f64 {
                            ret = Err("divided by zero".to_string())
                        } else {
                            ret = Ok(EvaluatedValue::new_number(ln - rn))
                        }
                    }
                    _ => {}
                }
            }
            TokenType::Greater => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_bool(ln > rn))
                    }
                    _ => {}
                }
            }
            TokenType::GreaterEqual => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_bool(ln >= rn))
                    }
                    _ => {}
                }
            }
            TokenType::Less => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_bool(ln < rn))
                    }
                    _ => {}
                }
            }
            TokenType::LessEqual => {
                match expr_tuple {
                    (EvaluatedValue::Literal(LiteralValue::Number(ln)), EvaluatedValue::Literal(LiteralValue::Number(rn))) => {
                        ret = Ok(EvaluatedValue::new_bool(ln <= rn))
                    }
                    _ => {}
                }
            }
            TokenType::EqualEqual => {
                match expr_tuple {
                    (EvaluatedValue::Literal(ln), EvaluatedValue::Literal(rn)) => {
                        ret = Ok(EvaluatedValue::new_bool(is_equal(ln, rn)))
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        ret
    }

    fn visit_grouping_expr(&mut self, expr: &Grouping) -> EvaluateResult {
        self.evaluate(&expr.expr)
    }

    fn visit_literal(&self, l: &Literal) -> EvaluateResult {
        Ok(EvaluatedValue::Literal(l.value.clone()))
    }

    fn visit_unary(&mut self, u: &Unary) -> EvaluateResult {
        let operator = &u.operator;
        let right = &u.right;
        let value = self.evaluate(right)?;
        match operator.t_type {
            TokenType::Minus => {
                match value {
                    EvaluatedValue::Literal(LiteralValue::Number(n)) => Ok(EvaluatedValue::new_number(-n)),
                    _ => Err(format!("invalid unary[operator={:?}, right value={:?}", operator, value))
                }
            }

            _ => Err(format!("invalid unary[operator={:?}, right value={:?}", operator, value))
        }
    }

    fn visit_triple(&mut self, t: &Triple) -> EvaluateResult {
        let judge_expr = &t.judge_expr;
        let true_expr = &t.judge_expr;
        let false_expr = &t.false_expr;
        let judge_value = self.evaluate(judge_expr)?;
        if is_truthy(&judge_value) {
            self.evaluate(true_expr)
        } else {
            self.evaluate(false_expr)
        }
    }

    fn visit_variable(&mut self, variable: &Variable) -> EvaluateResult {
        match self.lookup_variable(&variable.token, &Expression::Variable(variable.clone())) {
            None => Err(format!("undefined variable {}", &variable.token.lexeme)),
            Some(l) => Ok(l)
        }
    }

    fn visit_assign(&mut self, assign: &Assign) -> EvaluateResult {
        let token = &assign.name;
        let expr = &assign.value;
        let value = self.evaluate(expr)?;

        let expr = Expression::Assign(assign.clone());
        match self.locals.get(&expr) {
            None => {
                if self.globals.borrow_mut().assign(assign.name.lexeme.clone(), value.clone()) {
                    Ok(value)
                } else {
                    Err(format!("undefined variable {:}", token.lexeme))
                }
            }
            Some(v) => {
                if self.env.borrow_mut().assign_at(assign.name.lexeme.clone(), value.clone(), *v) {
                    Ok(value)
                } else {
                    Err(format!("undefined variable {:}", token.lexeme))
                }
            }
        }
    }

    fn visit_logical(&mut self, logical: &Logical) -> EvaluateResult {
        let left = &logical.left;
        let operator = &logical.operator;
        let right = &logical.right;
        let value = self.evaluate(left)?;
        match &operator.t_type {
            TokenType::Or => {
                if is_truthy(&value) {
                    Ok(value)
                } else {
                    self.evaluate(right)
                }
            },
            _ => {
                if is_truthy(&value) {
                    self.evaluate(right)
                } else {
                    Ok(value)
                }
            }
        }
    }

    fn visit_call_expr(&mut self, call: &Call) -> EvaluateResult {
        let mut callee_value = self.evaluate(&call.callee.clone())?;
        let mut arguments = Vec::new();
        for arg in call.arguments.iter() {
            arguments.push(self.evaluate(arg)?);
        }

        println!("callee = {:?}, arguments = {:?}", callee_value, arguments);

        match callee_value {
            EvaluatedValue::Literal(ref l) => Err(format!("Invalid function {}", callee_value.stringify())),
            EvaluatedValue::Call(c) => {
                c.call(self, &arguments)
            }
            EvaluatedValue::Instance(ref i) => Err(format!("Invalid function {}", callee_value.stringify())),
            EvaluatedValue::Class(ref cls) => {
                cls.call(self, &arguments)
                // let instance = LoxInstance::new(cls.clone());
                // Ok(EvaluatedValue::Instance(Rc::new(RefCell::new(instance))))
            }
        }
    }

    fn visit_get_expr(&mut self, expr: &Get) -> EvaluateResult {
        println!("visit get: {:?}", expr);
        let obj = self.evaluate(&expr.object)?;
        println!("visit get: {:?}, obj: {:?}", expr, obj);
        match obj {
            EvaluatedValue::Instance(ref i) => {
                println!("get instance: {:?}", i);
                match i.borrow().get(&expr.name) {
                    None => Err(format!("property {} missing", expr.name.lexeme)),
                    Some(v) => Ok(v)
                }
            }
            _ => Err("Only instances have fields".to_string())
        }
    }

    fn visit_set_expr(&mut self, expr: &Set) -> EvaluateResult {
        println!("visit set: {:?}", expr);
        let mut obj = self.evaluate(&expr.object)?;
        let value = self.evaluate(&expr.value)?;
        match obj {
            EvaluatedValue::Instance(mut i) => {
                i.borrow_mut().set(&expr.name, value.clone());
                println!("instance {:?}", i);
                Ok(value)
            }
            _ => Err("Only instances have fields".to_string())
        }
    }

    fn visit_this_expr(&mut self, expr: &This) -> EvaluateResult {
        match self.lookup_variable(&expr.keyword, &Expression::This(expr.clone())) {
            None => Err("undefined this".to_string()),
            Some(l) => Ok(l)
        }
    }

    fn visit_super_expr(&mut self, expr: &Super) -> EvaluateResult {
        let distance = self.locals.get(&Expression::Super(expr.clone())).unwrap();

        let superclass = match self.env.borrow().get_at("super", *distance).unwrap() {
             EvaluatedValue::Class(superclass ) => {
                 superclass
             }
             _ => {
                 return Err("impossible".to_string());
             }
         };

        let object = match self.env.borrow().get_at("this", *distance - 1) {
            None => {
                return Err("unrecognized this".to_string());
            }
            Some(v) => {
                match v {
                    EvaluatedValue::Instance(instance) => instance,
                    _ => {
                        return Err(format!("Unexpected object {:?}", v));
                    }
                }
            }
        };

        let method = match superclass.find_method(&expr.method.lexeme) {
            None => {
                return Err(format!("Undefined property '{}'", expr.method.lexeme));
            }
            Some(m) => m
        };

        let function = method.bind(object, false);
        Ok(EvaluatedValue::Call(Rc::new(function)))
    }
}

impl StmtVisitor<ExecResult> for Interpreter {
    fn visit_print_stmt(&mut self, stmt: &StmtPrint) -> ExecResult {
        let expr = &stmt.expr;
        let value = self.evaluate(expr).map_err(|e| ExecErr::Other(e))?;
        println!("{}", value.stringify());
        Ok(EvaluatedValue::nil())
    }

    fn visit_expr_stmt(&mut self, stmt: &StmtExpr) -> ExecResult {
        let expr = &stmt.expr;
        let _value = self.evaluate(expr).map_err(|e| ExecErr::Other(e))?;
        Ok(EvaluatedValue::nil())
    }

    fn visit_var_stmt(&mut self, stmt: &StmtVar) -> ExecResult {
        let token = &stmt.name;
        let expr = &stmt.initializer;
        let value = self.evaluate(expr).map_err(|e| ExecErr::Other(e))?;
        self.env.borrow_mut().define(token.lexeme.clone(), value);
        Ok(EvaluatedValue::nil())
    }

    fn visit_block_stmt(&mut self, stmt: &StmtBlock) -> ExecResult {
        let statements = &stmt.stmts;
        self.execute_block(statements, Environment::with_enclosing(self.globals.clone()))
    }

    fn visit_if_stmt(&mut self, stmt: &StmtIf) -> ExecResult {
        let condition = &stmt.condition;
        let then_stmt = &stmt.then_stmt;
        let else_stmt = &stmt.else_stmt;
        let cond_value = self.evaluate(condition).map_err(|e| ExecErr::Other(e))?;
        if is_truthy(&cond_value) {
            self.execute(then_stmt)
        } else {
            match else_stmt {
                Some(stmt) => {self.execute(stmt)}
                _ => Ok(EvaluatedValue::nil())
            }
        }
    }

    fn visit_while_stmt(&mut self, stmt: &StmtWhile) -> ExecResult {
        let condition = &stmt.condition;
        let body = &stmt.body;
        while is_truthy(&self.evaluate(condition).map_err(|e| ExecErr::Other(e))?) {
            match self.execute(body) {
                Ok(_) => {}
                Err(e) => {
                    match e {
                        ExecErr::Break => break,
                        ExecErr::Continue => continue,
                        ExecErr::Other(ee) => return Err(Other(ee)),
                        ExecErr::Return(v) => return Ok(v)
                    }
                }
            }
        }

        Ok(EvaluatedValue::nil())
    }

    fn visit_break_stmt(&self) -> ExecResult {
        Err(ExecErr::Break)
    }

    fn visit_continue_stmt(&self) -> ExecResult {
        Err(ExecErr::Continue)
    }

    fn visit_class_stmt(&mut self, stmt: &StmtClass) -> ExecResult {
        let mut methods = HashMap::new();

        if let Some(ref superclass) = stmt.superclass {
            let cls = self.evaluate(&Expression::Variable(superclass.clone())).map_err(|e| ExecErr::Other(e))?;
            match cls {
                EvaluatedValue::Class(ref cls) => {
                    self.env.borrow_mut().define(stmt.name.lexeme.clone(), EvaluatedValue::nil());
                    let env = Rc::new(RefCell::new(Environment::with_enclosing(self.env.clone())));
                    self.env = env;
                    self.env.borrow_mut().define("super".to_string(), EvaluatedValue::Class(cls.clone()));
                    for f in stmt.methods.iter() {
                        methods.insert(f.name.lexeme.clone(), Rc::new(LoxFunction::new(f.clone(), self.env.clone(), f.name.lexeme == "init")));
                    }

                    let prev_env = self.env.borrow().enclosing.as_ref().unwrap().clone();
                    self.env = prev_env;
                    self.env.borrow_mut().assign(stmt.name.lexeme.clone(), EvaluatedValue::Class(
                        LoxClass::with_superclass(&stmt.name.lexeme, methods, Rc::new(cls.clone()))
                    ));
                }
                _ => return Err(ExecErr::Other("Superclass must be a class.".to_string()))
            }
        } else {
            self.env.borrow_mut().define(stmt.name.lexeme.clone(), EvaluatedValue::nil());
            for f in stmt.methods.iter() {
                methods.insert(f.name.lexeme.clone(), Rc::new(LoxFunction::new(f.clone(), self.env.clone(), f.name.lexeme == "init")));
            }
            self.env.borrow_mut().assign(stmt.name.lexeme.clone(), EvaluatedValue::Class(
                LoxClass::new(&stmt.name.lexeme, methods)
            ));
        }

        Ok(EvaluatedValue::nil())
    }

    fn visit_function_stmt(&mut self, f: &StmtFunction) -> ExecResult {
        let lox_func = LoxFunction::new(f.clone(),  self.env.clone(), false);
        println!("define function {}", f.name.lexeme);
        self.env.borrow_mut().define(f.name.lexeme.clone(), EvaluatedValue::Call(Rc::new(lox_func)));
        Ok(EvaluatedValue::nil())
    }

    fn visit_return_stmt(&mut self, stmt: &StmtReturn) -> ExecResult {
        // let return_value = self.evaluate(&stmt.value).map_err(|e| Other(e))?;
        match stmt.value {
            None => {
                Err(ExecErr::Return(EvaluatedValue::nil()))
            },
            Some(ref v) => {
                Err(ExecErr::Return(self.evaluate(v).map_err(|e| Other(e))?))
            }
        }
    }
}

impl Interpreter {
    pub fn interpret(&mut self, statements: &[Stmt]) -> ExecResult {
        for stmt in statements {
            self.execute(stmt).map_err(|e| e)?;
        }

        Ok(EvaluatedValue::nil())
    }

    fn execute(&mut self, stmt: &Stmt) -> ExecResult {
        stmt.accept(self)
    }

    fn evaluate(&mut self, expr: &Expression) -> EvaluateResult {
        expr.accept(self)
    }

    pub fn execute_block(&mut self, statements: &[Stmt], env: Environment) -> ExecResult {
        let prev_env = self.env.clone();
        self.env = Rc::new(RefCell::new(env));
        let mut ret = Ok(EvaluatedValue::nil());
        for stmt in statements.iter() {
            match self.execute(stmt) {
                Ok(_) => {}
                Err(e) => {
                    ret = Err(e);
                    break;
                }
            }
        }

        self.env = prev_env;

        ret
    }

    pub fn resolve(&mut self, expr: Expression, depth: usize) {
        self.locals.insert(expr, depth);
    }

    fn lookup_variable(&self, name: &Token, expr: &Expression) -> Option<EvaluatedValue> {
        println!("lookup variable: {:?}", name);
        match self.locals.get(expr) {
            None => {
                println!("check globals");
                self.globals.borrow().get(name)
            },
            Some(distance) => {
                println!("check for distance {}", distance);
                self.env.borrow().get_at(&name.lexeme, *distance)
            }
        }
    }
}


#[derive(Clone, Debug)]
enum StackItem<'a> {
    Literal(LiteralValue),
    NormalExpr(&'a Expression),
    TripleExpr{ expr: &'a Expression, is_judged: bool}
}

impl Interpreter {
    // TODO: 迭代版本的求值
    /*
    pub fn visit_expr_iter(&mut self, expr: &Expression) -> EvaluateResult {
        let mut stack: Vec<StackItem> = Vec::new();

        let mut ret = Err("".to_string());
        let mut current_expr = expr;


        loop {
            match current_expr {
                Expression::Literal(l) => {
                    stack.push(StackItem::Literal(l.value.clone()));
                },
                Expression::Triple { judge_expr, true_expr, false_expr } => {
                    stack.push(StackItem::TripleExpr { expr, is_judged: false });
                    current_expr = judge_expr;
                    continue;
                },
                Expression::Grouping(g) => {
                    current_expr = g;
                    continue;
                }

                Expression::Binary { left, operator, right } => {
                    stack.push(StackItem::NormalExpr(current_expr));
                    current_expr = left;
                    continue;
                }
                Expression::Unary { operator, right } => {
                    stack.push(StackItem::NormalExpr(current_expr));
                    current_expr = right;
                    continue;
                }
                Expression::Variable(token) => {
                    todo!()
                }
                Expression::Assign { name, value } => {
                    todo!()
                }
                Expression::Logical { .. } => {}
                Expr::Logical { .. } => {}
                Expr::Call { .. } => {}
            }

            // 求值过程
            // 栈顶是literal，弹出元素直至是一个表达式，看是否可以求出此表达式的值
            // 如果可以，就将其计算出来，并替代原来的表达式
            // 如果否则，则将嵌套的表达式压栈
            loop {
                // println!("stack: {:?}", stack);
                let mut last_expr_op: Option<StackItem> = None;
                let mut literals: Vec<LiteralValue> = Vec::new();

                loop {
                    match stack.pop() {
                        None => break,
                        Some(exp) => {
                            match exp {
                                StackItem::Literal(l) => {
                                    literals.push(l);
                                }

                                _ => {
                                    last_expr_op = Some(exp);
                                    break;
                                }
                            }
                        }
                    }
                }

                // println!("last expr: {:?}, literals: {:?}", last_expr_op, literals);

                match last_expr_op {
                    None => {
                        return if literals.len() == 1 {
                            Ok((*literals.first().unwrap()).clone())
                        } else {
                            Err(format!("empty operator with multiple literal values: {:?}", literals))
                        }
                    }
                    Some(i) => {
                        match i {
                            StackItem::NormalExpr(e) => {
                                match e {
                                    Expression::Binary { left, operator, right } => {
                                        if literals.len() == 2 {
                                            let left_arg = literals.pop().unwrap();
                                            let right_arg = literals.pop().unwrap();
                                            let value = self.visit_binary_expr(&Expression::Literal(left_arg.clone()), operator, &Expression::Literal(right_arg.clone()))?;
                                            // println!("calculated binary ({:?} {:?} {:?}) value: {:?}", right_arg, left_arg, operator.t_type, value);
                                            stack.push(StackItem::Literal(value));
                                        } else if literals.len() == 1 {
                                            // 只有一个literal计算出来，将右叶子压栈
                                            stack.push(i);
                                            while !literals.is_empty() {
                                                stack.push(StackItem::Literal(
                                                    literals.pop().unwrap()
                                                ));
                                            }
                                            current_expr = right;
                                            // println!("arguments not ready, recover stack: {:?}", stack);
                                            break;
                                        } else {
                                            return Err(format!("impossible binary argument list: {:?}", literals));
                                        }
                                    }
                                    Expression::Unary { operator, right } => {
                                        if literals.len() != 1 {
                                            return Err(format!("invalid unary arguments: {:?}", literals));
                                        } else {
                                            let value = self.visit_unary(operator, &Expression::Literal(literals.pop().unwrap().clone()))?;
                                            for _ in 0..literals.len() + 1 { stack.pop(); }
                                            stack.push(StackItem::Literal(value));
                                        }
                                    }
                                    _ => return Err(format!("impossible normal expression: {:?}", e))
                                }
                            }

                            StackItem::TripleExpr { expr, is_judged } => {
                                if literals.len() != 1 {
                                    return Err(format!("invalid triple expressions: {:?}", literals));
                                }

                                match expr {
                                    Expression::Triple { judge_expr, true_expr, false_expr } => {
                                        for _ in 0..literals.len() + 1 { stack.pop(); }
                                        let check_literal = literals.pop().unwrap();
                                        if is_judged {
                                            stack.push(StackItem::Literal(
                                                (*literals.first().unwrap())
                                                    .clone()
                                            ));
                                        } else {
                                            if is_truthy(&check_literal) {
                                                current_expr = true_expr;
                                            } else {
                                                current_expr = false_expr;
                                            }
                                            break;
                                        }
                                    }
                                    _ => {}
                                }
                            }
                            _ => {}
                        }
                    }
                }
            }
        }

        ret
    }*/
}

fn eval(s: &str) -> EvaluateResult {
    let mut scanner = Scanner::new(s);
    let tokens = scanner.scan_tokens().unwrap();
    let mut interpreter = Interpreter::new();
    let mut parser = Parser::new(tokens);
    let expr = parser.expression().map_err(|e| e)?;
    // interpreter.visit_expr_iter(&expr)
    // expr.accept(&mut interpreter)
    interpreter.evaluate(&expr)
}

fn exec(s: &str) -> ExecResult {
    let mut scanner = Scanner::new(s);
    let tokens = scanner.scan_tokens().unwrap();
    let mut interpreter = Interpreter::new();
    let mut parser = Parser::new(tokens);
    let stmts = parser.parse().map_err(|e| ExecErr::Other(e))?;
    println!("stmts: {:?}", stmts);
    for stmt in stmts.iter() {
        interpreter.execute(stmt)?;
    }

    Ok(EvaluatedValue::nil())
}

fn get_invalid_binary_error(left: &Expression, operator: &Token, right: &Expression) -> EvaluateResult {
    Err(format!("invalid binary expression: left={:?}, operator={:?}, right={:?}", left, operator, right))
}

fn is_equal(l: &LiteralValue, r: &LiteralValue) -> bool {
    match (l, r) {
        (LiteralValue::Bool(lb), LiteralValue::Bool(rb)) => lb == rb,
        (LiteralValue::Nil, LiteralValue::Nil) => true,
        (LiteralValue::String(ls), LiteralValue::String(rs)) => ls == rs,
        (LiteralValue::Number(ln), LiteralValue::Number(rn)) => ln == rn,
        _ => false
    }
}

fn is_truthy(value: &EvaluatedValue) -> bool {
    match value {
        EvaluatedValue::Literal(v) => {
            match v {
                LiteralValue::String(_) => true,
                LiteralValue::Number(_) => true,
                LiteralValue::Bool(b) => *b,
                LiteralValue::Nil => false,
                LiteralValue::Empty => false
            }
        }
        _ => true
    }
}

#[cfg(test)]
mod test {
    use crate::expr::ExprVisitor;
    use crate::interpreter::{eval, Interpreter, exec};
    use crate::parser::Parser;
    use crate::scanner::Scanner;

    #[test]
    fn evaluate_test() {
        let ss = "1 + 2 > 10? 3+4 > 5? 1: 2 : 9";
        println!("{:?}", eval(ss));
        println!("{:?}", eval("-2"));

        println!("{:?}", eval("2 + 10 * 5 - 1"));
        println!("{:?}", eval("(2 + 10) * 5 - 1"));

        let s = "1 + 2 > 10? 10: 9";
        println!("{:?}", eval(s));

        println!("{:?}", eval("\"a\" + \"b\""));
        println!("{:?}", eval("a+b"));
    }

    #[test]
    fn if_test() {
        let if_s = "var a = 1; \
        if (a) {\
           print 1;
        } else {\
           print 2;
        }";

        println!("{:?}", exec(if_s));
    }

    #[test]
    fn while_test() {
        let s = "var i = 1;
        var sum = 0;
        while (i < 10) {
            sum = sum + 1;
            i = i + 1;
        }
        print sum;
        ";

        println!("{:?}", exec(s));
    }

    #[test]
    fn for_test() {
        let s = "for (var i = 0;i < 10;i = i + 1) {\
          print i;
          if (i > 7) {
             break;
          }
        }";

        println!("{:?}", exec(s));
    }

    #[test]
    fn clock_fn_test() {
        let s = "print clock();";

        println!("{:?}", exec(s));
    }

    #[test]
    fn function_definition_test() {
        let s = "fun add(a, b) {\
            return a+b;
        }
        print 1+1;
        ";

        println!("{:?}", exec(s));
    }
}